//
//  main.c
//  message_cgi
//
//  Created by lijinxin on 12-5-1.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#define MYSQL_HEADER_PATH "/usr/local/mysql/include/mysql.h"
#define FCGI_HEADER_PATH "/usr/local/include/fastcgi.h"
#define FCGI_STDIO_HEADER_PATH "/usr/local/include/fcgi_stdio.h"

//#include <unistd.h>
//#include <stdlib.h>
#include <time.h>
#include <stdio.h>
typedef FILE* (*fopen_func) (const char *, const char *);
typedef size_t (*fread_func) (void *, size_t, size_t, FILE *);
typedef size_t (*fwrite_func) (const void *, size_t, size_t, FILE *);
typedef int (*fclose_func) (FILE *);

static fopen_func raw_fopen = fopen;
static fread_func raw_fread = fread;
static fwrite_func raw_fwrite = fwrite;
static fclose_func raw_fclose = fclose;

#include "/usr/local/include/fcgi_stdio.h"
//#include FCGI_STDIO_HEADER_PATH
#include MYSQL_HEADER_PATH

//定义数据库操作的宏，也可以不定义留着后面直接写进代码
#define SELECT_QUERY "select * from messages"
#define INSERT_QUERY_TEST "insert into messages values(\"2012-05-03 00:00:16\",\"C应用\",\"这是另外的一个测试啊测试啊测试啊测试！！！！！\");"
#define INSERT_QUERY "insert into messages values(\"%s\",\"%s\",\"%s\");"

//内存池，防止大数据溢出
#define MEM_POOL_SIZE (16*1024*1024)
static unsigned char* g_mem_pool = NULL;

MYSQL* dbma_mysql_create()
{
    return NULL;
}

void dbma_mysql_destroy(MYSQL* obj)
{
}

int dbma_mysql_insert_to_db(char* datetime, char* user_name, char* content)
{
    MYSQL mysql = {0},*sock = NULL;   //定义数据库连接的句柄，它被用于几乎所有的MySQL函数
    MYSQL_RES *res = NULL;     //查询结果集，结构类型
    MYSQL_FIELD *fd = NULL;   //包含字段信息的结构
    MYSQL_ROW row = {0};     //存放一行查询结果的字符串数组
    char* qbuf = NULL;     //存放查询sql语句字符串
    int qbuf_len = 0;
    int i = 0;
    
    mysql_init(&mysql);
    if (!(sock = mysql_real_connect(&mysql,"localhost","root","","message_db",0,NULL,0))) {
        fprintf(stdout,"Couldn't connect to engine!\n%s\n\n",mysql_error(&mysql));
        goto ERR_HANDLEER;
    }
    
    if (!mysql_set_character_set(sock, "utf8"))
    {
        printf("New client character set: %s\n", mysql_character_set_name(sock));
    }
    
    //INSERT TEST
    qbuf_len = strlen(INSERT_QUERY) + strlen(datetime) + strlen(user_name) + strlen(content) + 1;
    qbuf = malloc(qbuf_len);
    memset(qbuf, 0, qbuf_len);
    snprintf(qbuf, qbuf_len, INSERT_QUERY, datetime, user_name, content);
    if(mysql_query(sock,qbuf))
    {
        fprintf(stdout,"Insert failed (%s)\n",mysql_error(sock));
        goto ERR_HANDLEER;
    }
    else
    {
        printf("Insert %llu rows\n", mysql_affected_rows(sock));
    }
    
    //SELECT
    if(mysql_query(sock,SELECT_QUERY)) {
        fprintf(stdout,"Query failed (%s)\n",mysql_error(sock));
        goto ERR_HANDLEER;
    }
    
    if (!(res=mysql_store_result(sock))) {
        fprintf(stdout,"Couldn't get result from %s\n", mysql_error(sock));
        goto ERR_HANDLEER;
    }
    
    printf("number of fields returned: %d\n",mysql_num_fields(res));
    
    while (row = mysql_fetch_row(res)) {
        printf("Table result is:") ; 
        for (i = 0; i < res->field_count; ++i)
        {
            printf((((row[i]==NULL)&&(!strlen(row[i]))) ? "NULL" : row[i])) ;
        }
        printf("\n");
        //puts( "query ok !\n" ) ; 
    } 
    
    free(qbuf);
    mysql_free_result(res);
    mysql_close(sock);
    
    return 0;
ERR_HANDLEER:
    if (qbuf)
    {
        free(qbuf);
    }
    if (res)
    {
        mysql_free_result(res);
    }
    if (sock)
    {
        mysql_close(sock);
    }
    return -1;
}

void refresh_xml(char* xml_path)
{
}

int URLDecoder(char* buf)
{
    int i = 0;
    int j = 0;
    char t[5] = "0x00";
    while (buf[i] != 0)
    {
        if (buf[i] == '%')
        {
            t[2] = buf[i+1];
            t[3] = buf[i+2];
            buf[j] = (char)strtol(t, NULL, 16);
            i += 3;
        }
        else
        {
            buf[j] = buf[i];
            ++i;
        }
        ++j;
    }
    buf[j] = 0;
    return j;
}

void get_current_datetime(char* buf)
{
    struct   tm     *ptm; 
    long       ts; 
    int         y,m,d,h,n,s; 
    
    ts   =   time(NULL); 
    ptm   =   localtime(&ts); 
    
    y   =   ptm-> tm_year+1900; //年
    m   =   ptm-> tm_mon+1; //月 
    d   =   ptm-> tm_mday;  //日 
    h   =   ptm-> tm_hour;  //时 
    n   =   ptm-> tm_min;   //分 
    s   =   ptm-> tm_sec;   //秒
    
    sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", y,m,d,h,n,s);
}

void parse_and_refresh(char* buffer, int length)
{
#define USER_NAME_PRE "user_name="
#define CONTENT_PRE "content="
    char* last_ptr = buffer;
    char* user_name = NULL;
    char* content = NULL;
    char* t_ptr = NULL;
    char datetime[64] = {0};
    int i = 0;
    
    get_current_datetime(datetime);
    
    while (i < length)
    {
        if (buffer[i] == '&')
        {
            if (!user_name && (t_ptr = strstr(last_ptr,USER_NAME_PRE)) != NULL)
            {
                user_name = t_ptr + strlen(USER_NAME_PRE);
            }
            else if(!content && (t_ptr = strstr(last_ptr,CONTENT_PRE)) != NULL)
            {
                content = t_ptr + strlen(CONTENT_PRE);
            }
            buffer[i] = 0;
            last_ptr = &buffer[i+1];
        }
        ++i;
    }
    
    printf("<br>Parsed datetime = %s, user_name = %s, content = %s<br>\r\n", datetime, user_name, content);
    
    dbma_mysql_insert_to_db(datetime, user_name, content);
}

void deal_with()
{
#define MAX_CONTENT_LEN (4096)
    extern char   **environ;
    int nlen = 0;
    int i;
    char szContent[MAX_CONTENT_LEN + 1] = {0};
    char **penv;
    char *req = NULL;
    int mempool_ptr = 0;
    
    printf("Content-type: text/html; charset=utf8\n\n");
    
    if (1/* strcmp("POST", getenv("REQUEST_METHOD")) == 0 */)
    {
        if (1/*getenv("CONTENT_LENGTH")*/)
        {
            FILE* hf = fopen("./fcgi_test.txt", "wb");
            printf("<title></title>\r\n<body>\r\n");
            
            printf("Submited:<br>\r\n");
            while (!feof(stdin))
            {
                memset(szContent, 0, MAX_CONTENT_LEN);
                nlen = fread(szContent, 1, MAX_CONTENT_LEN, stdin);
                nlen = URLDecoder(szContent);
                fwrite(szContent, 1, nlen, hf);
                fwrite(szContent, 1, nlen, stdout);
                memcpy(&g_mem_pool[mempool_ptr],szContent,nlen);
                mempool_ptr += nlen;
                //printf(szContent);
            }
            printf("<br>\r\nMySQL LOG:<br>\r\n");
            
            g_mem_pool[mempool_ptr] = 0;
            parse_and_refresh(g_mem_pool, mempool_ptr + 1);
            
            printf("\r\n</body>");
            fclose(hf);
        }
        else
        {
            printf("<p>shit!</p>");
        }
    }
    else
    {
        //printf("<p>%s</p>", getenv("QUERY_STRING"));
    }
}

int main(int argc, const char * argv[])
{
    int count = 0;
    
    g_mem_pool = malloc(MEM_POOL_SIZE);
    
    while (FCGI_Accept() >= 0)
    {
        deal_with();
        /*FILE* hf = fopen("./fcgi_test.txt", "wb");
        if (hf == NULL)
        {
            printf("Content-type: text/html\r\n"
                   "\r\n"
                   "<title>FOPEN FAILED!</title>"
                   "<h1>FOPEN FAILED!</h1>"
                   );
        }
        else
        {
            fwrite("just test!", 1, sizeof("just test!"), hf);
            fclose(hf);
            printf("Content-type: text/html\r\n"
                   "\r\n"
                   "<title>FILE OPT SUCCEED!</title>"
                   "<h1>FILE OPT SUCCEED!</h1>"
                   );
        }*/
         
        /*printf("Content-type: text/html\r\n"
               "\r\n"
               "<title>FastCGI Hello! (C, fcgi_stdio library)</title>"
               "<h1>FastCGI Hello! (C, fcgi_stdio library)</h1>"
               "Request number %d running on host <i>%s</i>\n"
               ,++count, getenv("SERVER_HOSTNAME"));*/
        FCGI_Finish();
    }
    
    free(g_mem_pool);
    
    return 0;
}

